﻿using System;
using System.Collections.Generic;
using System.Text;

namespace sign_recognition
{
    public class FuzzyART
    {
        public String currentOutput;
        public InputLayer F1;
        public OutputLayer F2;
        public bool codingComplement;
        public FuzzyART() {

        }


       /* public FuzzyART(Double[] inputVector, bool codingComplement, Double alpha, Double rho, Double beta, int firstOutput)
        {
            this.codingComplement = codingComplement;
            this.F1 = new InputLayer(inputVector, this.codingComplement);//input layer
            //Console.WriteLine(F1);

            //output layer
            //The weight vector's size is equal to the dimension M of layer F1
            //The number of potential categories N(j = i . . . . . N) is arbitrary

            this.F2 = new OutputLayer(F1,alpha,rho,beta);
            this.F2.evaluateEachNeuron();
            //Console.WriteLine(F2);
          //  this.F2.printTArray();
            //Console.WriteLine(this.F2.getWinningCategory());

            this.F2.updateWeightsOfWinningCategory(inputVector,firstOutput);

          //  this.F2.evaluateEachNeuron();
           // Console.WriteLine(this.F2.getWinningCategory());

            //Console.WriteLine(this.F2.getWinningCategory());


         //   this.F2.printTArray();
            this.F2.printWeightsToText();
           // Double[] x = { 0.2, 0.6, 0.2, 0.2, 0.6, 0.99999992 };
           // Double[] y = { 0.1, 0.5, 0.02, 0.2, 0.6, 0.99999993 };
          //  Category c = new Category(2);


           // Console.WriteLine(c.doubleArrayToString(c.fuzzyAND(x, y)));
           // Console.WriteLine(c.computeNorm(y));
        }*/
        public FuzzyART(Double[] inputVector, bool codingComplement, Double alpha, Double rho, Double beta)
        {
            this.codingComplement = codingComplement;
            this.F1 = new InputLayer(inputVector, this.codingComplement);//input layer

            //Console.WriteLine(F1);

            //output layer
            //The weight vector's size is equal to the dimension M of layer F1
            //The number of potential categories N(j = i . . . . . N) is arbitrary

            this.F2 = new OutputLayer(F1, alpha, rho, beta);



            /*

            this.F2.evaluateEachNeuron();

            this.F2.updateWeightsOfWinningCategory(inputVector, firstOutput);

            this.F2.printWeightsToText();*/

        }
        public FuzzyART(int inputVectorSize, bool codingComplement, Double alpha, Double rho, Double beta)
        {
            this.codingComplement = codingComplement;

            this.F1 = new InputLayer(inputVectorSize, codingComplement);

          //  List<Category> categories = this.loadWeights(categoriesFile);
            this.F2 = new OutputLayer(F1, alpha, rho, beta);
            //this.F2 = new OutputLayer(F1, alpha, rho, beta, categories);



        }
        public FuzzyART(int inputVectorSize, bool codingComplement, Double alpha, Double rho, Double beta, String categoriesFile)
        {
            this.codingComplement = codingComplement;

            this.F1 = new InputLayer(inputVectorSize, codingComplement);
            //Console.WriteLine(F1);

            //output layer
            //The weight vector's size is equal to the dimension M of layer F1
            //The number of potential categories N(j = i . . . . . N) is arbitrary
            List<Category> categories=this.loadWeights(categoriesFile);
            this.F2 = new OutputLayer(F1, alpha, rho, beta, categories);



            /*

            this.F2.evaluateEachNeuron();

            this.F2.updateWeightsOfWinningCategory(inputVector, firstOutput);

            this.F2.printWeightsToText();*/

        }


        public void propagateNewInput(Double[] inputVector){
            this.F1.newInput(inputVector,this.codingComplement);
            this.F2.I = F1.I;
            this.F2.evaluateEachNeuron();
            this.F2.updateWeightsOfWinningCategory(inputVector,this.currentOutput);
            this.F2.printWeightsToText();
        }
        public void propagateNewInput(Double[] inputVector,String output)
        {
            this.F1.newInput(inputVector, this.codingComplement);
            this.F2.I = F1.I;
            this.F2.evaluateEachNeuron();
            this.F2.updateWeightsOfWinningCategory(F2.I, output);
            this.F2.printWeightsToText();
        }
        public String clasify(Double[] inputVector)
        {
            this.F1.newInput(inputVector, this.codingComplement);
            this.F2.I = F1.I;
            this.F2.evaluateEachNeuron();
            return this.F2.clasify().output;
        }

        public void saveWeights(String fileName) {
            this.F2.saveWeights(fileName);
        }

        public List<Category> loadWeights(String fileName)
        {
            ReadFile readFile = new ReadFile(fileName);

            List<Category> categories = new List<Category>() ;
            Weights w = new Weights();

            w = readFile.readWeights();
            while (null != w)
            {
                categories.Add(new Category(w));
                w = readFile.readWeights();
                
            } 
           
            readFile.close();
            return categories;
        }

    }
}
